# -*- coding: iso-8859-1 -*-

__author__ = "Vincent"
__date__ = "$1 mars 2009 13:41:04$"

"""
COMPONENTES IN THE CATANE GAME
resource_fields 37 + 15
 * earth
   * lumber 4 + 2
   * brick 3 + 2
   * wool 4 + 2
   * grain 4 + 2
   * ore 3 + 2
   * desert 1 + 1
 * sea
   * water 9 + 2
   * port3 4 + 1
   * port2
     * port2lumber 1
     * port2brick 1
     * port2wool 1 + 1
     * port2grain 1
     * port2ore 1
cards
 * resource cards
   * lumber 19
   * brick 19
   * wool 19
   * grain 19
   * ore 19
 * development cards
   * knight cards 14
   * victory point cards 5
   * others 6
     * requisition 2
     * build road 2
     * free resources 2
certificates 2
 * longest road 1
 * almighty knight 1
set of pawns 4 + 2
 * roads set*15
 * villages set*5
 * cities set*4
thief 1
numbered chips
 * A = 5
 * B = 2
 * C = 6
 * D = 3
 * E = 8
 * F = 10
 * G = 9
 * H = 12
 * I = 11
 * J = 4
 * K = 8
 * L = 10
 * M = 9
 * N = 4
 * O = 5
 * P = 6
 * Q = 3
 * R =11
"""
import random

class GameComponents:
    """
    Class holding all game components according to number of players
    usage : game_components = GameComponents(number_of_players)
    """
    #number of players (default = 4)
    number_of_players = 4

    #resources constantes
    resource_fields = {}
    """
    resource_fields = {'resource_type':nb_resource}
    """
    EARTH_FIELDS = 'earth_fields'
    LUMBER = 'lumber'
    BRICK = 'brick'
    WOOL = 'wool'
    GRAIN = 'grain'
    ORE = 'ore'
    DESERT = 'desert'
    SEA_FIELDS = 'sea_fields'
    WATER = 'water'
    PORT3 = 'port3'
    PORT2 = 'port2'
    PORT2LUMBER = 'port2lumber'
    PORT2BRICK = 'port2brick'
    PORT2WOOL = 'port2wool'
    PORT2GRAIN = 'port2grain'
    PORT2ORE = 'port2ore'

    #cards
    RESOURCE_CARDS = 'resource_cards'
    DEVELOPMENT_CARDS = 'development cards'
    KNIGHT_CARDS = 'knight cards'
    VICTORY_CARDS = 'victory cards'
    MISCELLANOUS_CARDS = 'miscellanous cards'
    MONOPOLY_CARDS = 'monopoly cards'
    TWO_ROAD_CARDS = 'two road cards'
    TWO_RESOURCE_CARDS = 'two resource cards'
    cards = {RESOURCE_CARDS:{
                         LUMBER:19,
                         BRICK:19,
                         WOOL:19,
                         GRAIN:19,
                         ORE:19},
              DEVELOPMENT_CARDS:{
                         KNIGHT_CARDS:14,
                         VICTORY_CARDS:5,
                         MISCELLANOUS_CARDS:{
                                MONOPOLY_CARDS:2,
                                TWO_ROAD_CARDS:2,
                                TWO_RESOURCE_CARDS:2}}}
    """
    cards = {'card_type':nb_cards}
    """

    #certificates
    LONGEST_ROAD = 'longest road'
    ALMIGHTY_KNIGHT = 'almighty'

    #chip list
    chips = (5,2,6,3,8,10,9,12,11,4,8,10,9,4,5,6,3,11)

    def __init__(self, number_of_players=4):
        """
        number_of_players as integer from 2 to 4
        resource_field as dictionnary
        cards as dictionnary
        chips as tuple
        """

        self.number_of_players = number_of_players

        #set modificators according to number of players
        more = 0
        if 5 <= number_of_players <= 6:
            more = 1

        #set the resources
        self.resource_fields = {self.EARTH_FIELDS:{
                                     self.LUMBER:4+more*2,
                                     self.BRICK:3+more*2,
                                     self.WOOL:4+more*2,
                                     self.GRAIN:4+more*2,
                                     self.ORE:3+more*2,
                                     self.DESERT:1+more},
                                 self.SEA_FIELDS:{
                                     self.WATER:9+more*2,
                                     self.PORT3:4+more,
                                     self.PORT2:{
                                         self.PORT2LUMBER:1,
                                         self.PORT2BRICK:1,
                                         self.PORT2WOOL:1+more,
                                         self.PORT2GRAIN:1,
                                         self.PORT2ORE:1}}}

class ResourceFieldManager:
    """
    Claaa to manage resource fields according to number of available resource fields
    takeResourceField('resource') return 'resource'
    giveResourceField('resource') return 'resource'
    """

    resource_fields_ref = None
    resource_fields = None

    def __init__(self, number_of_players=4):
        components = GameComponents(number_of_players)
        self.resource_fields_ref = components.resource_fields
        self.resource_fields = dict(components.resource_fields) #working copy

    def __doResourceField(self,resource, takeGiveFlag):
        #allow add 1 or take 1
        if takeGiveFlag != 1 and takeGiveFlag!=-1: return None
        #some constants to improve code readibility
        EARTH_FIELDS = GameComponents.EARTH_FIELDS
        SEA_FIELDS = GameComponents.SEA_FIELDS
        PORT2 = GameComponents.PORT2
        PORT3 = GameComponents.PORT3
        WATER = GameComponents.WATER
        #resource might be earth_fields resources
        if resource in self.resource_fields[EARTH_FIELDS]:
            if -takeGiveFlag <= self.resource_fields[EARTH_FIELDS][resource] <= self.resource_fields_ref[EARTH_FIELDS][resource] -takeGiveFlag:
                self.resource_fields[EARTH_FIELDS][resource] += takeGiveFlag
                return resource
        #resource might be port2 resources
        elif resource in self.resource_fields[SEA_FIELDS][PORT2]:
            if -takeGiveFlag <= self.resource_fields[SEA_FIELDS][PORT2][resource] <= self.resource_fields_ref[SEA_FIELDS][PORT2][resource] -takeGiveFlag:
                self.resource_fields[SEA_FIELDS][PORT2][resource] += takeGiveFlag
                return resource
        #resource might be port3
        elif resource == PORT3:
            if -takeGiveFlag <= self.resource_fields[SEA_FIELDS][PORT3] <= self.resource_fields_ref[SEA_FIELDS][PORT3] -takeGiveFlag:
                self.resource_fields[SEA_FIELDS][PORT3] += takeGiveFlag
                return resource
        #resource might be plain water
        elif resource == WATER:
            if -takeGiveFlag <= self.resource_fields[SEA_FIELDS][WATER] <= self.resource_fields_ref[SEA_FIELDS][WATER] -takeGiveFlag:
                self.resource_fields[SEA_FIELDS][WATER] += takeGiveFlag
                return resource

        else: return None

    def giveResourceField(self,resource):
        """
        Give back 'resource_name' and remember
        return 'resource_name'
        """
        return self.__doResourceField(resource,1)

    def takeResourceField(self,resource):
        """
        Take 'resource_name' and remember
        return 'resource_name'
        """
        return self.__doResourceField(resource,-1)

    def takeRandomEarthField(self):
        """
        Take a random 'resource_name' of earth type and remember
        return 'resource_name'
        """
        #try to take a random resource among remaining (>0 in dictionary)
        li = self.resource_fields[GameComponents.EARTH_FIELDS].keys()
        #remove if value 0 in dictionary
        for resource in li[:]: #use a copy of li because of li.remove
            if self.resource_fields[GameComponents.EARTH_FIELDS][resource] < 1:
                li.remove(resource)
        #if empty return
        if li == []:return None
        #return random element among remaining
        return self.takeResourceField(li[random.randint(0, len(li)-1)])

    def takeRandomSeaField(self):
        """
        Take a random 'resource_name' of sea type and remember
        return 'resource_name'
        """
        #some constants to improve code readibility
        SEA_FIELDS = GameComponents.SEA_FIELDS
        PORT2 = GameComponents.PORT2
        #sea_fields and subcase port2
        li1 = self.resource_fields[SEA_FIELDS].keys()
        li2 = self.resource_fields[SEA_FIELDS][PORT2].keys()
        #remove if value 0 in dictionary
        for resource in li1[:]: #use a copy of li because of li.remove
            if self.resource_fields[SEA_FIELDS][resource] < 1:
                li1.remove(resource)
        li1.remove(PORT2)
        for resource in li2[:]: #use a copy of li because of li.remove
            if self.resource_fields[SEA_FIELDS][PORT2][resource] < 1:
                li2.remove(resource)
        #if empty return
        li = li1 + li2
        if li == []: return None
        #return random element among remaining
        a = li[random.randint(0, len(li)-1)]
        b = self.takeResourceField(a)
        if not b:
            print 'a : ',a,'b : ',b, '\n'
        return b  
    
if __name__ == "__main__":
    #testing
    compo = GameComponents()
    print compo.resource_fields, '\n'
    print compo.cards, '\n'
    print compo.chips,'\n'
    m = ResourceFieldManager()
    print 'resource_fields : ',m.resource_fields,'\n'
    print 'resource_fields_ref : ',m.resource_fields_ref,'\n'
    r = range(20)
    for i in r:
        print 'random earth : ' , m.takeRandomEarthField(),"\trandom sea : ",m.takeRandomSeaField(),'\n'
    print 'resource_fields : ',m.resource_fields,'\n'
    print 'resource_fields_ref : ',m.resource_fields_ref,'\n'

    print '----------take ORE-------\n'
    m.takeResourceField(GameComponents.ORE)
    print 'resource_fields : ',m.resource_fields,'\n'
    print '------give LUMBER------\n'
    m.giveResourceField(GameComponents.LUMBER)
    print 'resource_fields : ',m.resource_fields,'\n'


